<script setup lang="ts">
import {ref, useSlots, watch} from 'vue';
import {ElCol, ElForm, ElCard, ElIcon, ElButton, ElFormItem} from 'element-plus'; // 引入 Element Plus 组件
import {devSearchFormProps, SearchList} from './searchForm';
import DevSelect from "@/components/DevSelect";
import DevDatePicker from "@/components/DevDatePicker";
import DevInput from "@/components/DevInput";
import DevCascader from "@/components/DevCascader";
import {ArrowDownBold, ArrowUpBold} from '@element-plus/icons-vue';
import type {FormInstance} from 'element-plus';
import {devDeepMerge, useConfig} from "@/index";

const slots = useSlots();
const props = defineProps(devSearchFormProps)
// elDatePickerProps配置
const defaultFormProps = useConfig().elFormProps;
const formData = ref<{ [key: string]: any }>({}); // 表单数据
const expand = ref(false); // 是否展开
const emit = defineEmits(['search', 'reset']);
const formRef = ref<FormInstance>();
// 校验通过
const submitForm = async () => {
  await formValidate().then((res: any) => {
    if (res) emit('search', formData.value); // 当点击查询按钮，并检验成功后向外抛出当前form表单绑定当数据
  }).catch((err) => {
    console.error('筛选项校验失败，请检查!', err);
  })
};

/**
 * 校验表单
 * @returns Promise
 */
const formValidate = () => {
  return new Promise((resolve, reject) => {
    const formEl = formRef.value;
    if (!formEl) return;
    formEl.validate((valid, fields) => {
      resolve(valid);
      if (!valid) {
        reject(fields);
      }
    });
  })
};

// 子项显示逻辑
const isShowCol = (item: SearchList) => {
  // 如果当前项需要隐藏，直接隐藏
  if (item?.isHidden) return false;
  // 如果当前处于开启折叠状态，且当前项是默认折叠项
  return !(!expand.value && props.isCollapse && item?.defaultCollapse);
};
// 点击重置按钮
const resetForm = () => {
  if (!formRef.value) return;
  formRef.value.resetFields();
  emit('reset'); // 当点击重置按钮时向外抛出重置事件
};

type ComponentType = 'input' | 'select' | 'cascader' | 'datePicker';
// 日期相关的组件类型
const components: Record<ComponentType, any> = {
  input: DevInput,
  select: DevSelect,
  cascader: DevCascader,
  datePicker: DevDatePicker
};

/**
 * 获取组件信息
 */
const getComponent = (type: ComponentType) => {
  return components[type] || null;  // 如果没有匹配类型，返回 null
};

/**
 * 获取插槽信息
 */
const getSlot = (key: string | string[]) => {
  if (Object.prototype.toString.call(key) === '[object Array]') {
  } else {
    let result: string[] = []
    Object.keys(slots).forEach((item) => {
      if (item.includes('_')) {
        let key_ = item.split('_')[0]
        let slot_ = item.split('_')[1]
        if (key_ === 's-' + key) {
          result.push(slot_)
        }
      }
    })
    return result;
  }
}

// 监听数据变化
watch(() => props.formValue, (val) => {
  formData.value = val;
}, {deep: true, immediate: true});

defineOptions({
  name: 'DevSearchForm',
  inheritAttrs: false
});

defineExpose({
  formValidate,
  resetForm,
  formRef
})

</script>

<template>
  <el-card class="search">
    <el-form
        ref="formRef"
        :scroll-to-error="true"
        :model="formData"
        @submit.prevent="submitForm()"
        v-bind="devDeepMerge(defaultFormProps,props.elFormAttrs)"
    >
      <el-row :gutter="24">
        <template v-for="i in props.searchList" :key="i.key.toString()">
          <el-col v-if="isShowCol(i)" v-bind="i.elColAttrs?i.elColAttrs:props.elColAttrs">
            <!--            如果是时间组件并且是区间的情况下走这个逻辑-->
            <el-form-item v-bind="{prop:i.key[0],label:i.label,...i.elFormItemAttrs}"
                          v-if="['datePicker'].includes(i.type) && Object.prototype.toString.call(i.key) === '[object Array]' && i.key.length === 2">
              <el-form-item v-bind="{prop:i.key[1]}"></el-form-item>
              <component
                  v-bind="{...(i?.devAttrs || {})}"
                  separateBinding
                  v-model:startTime="formData[i.key[0]]"
                  v-model:endTime="formData[i.key[1]]"
                  :is="getComponent('datePicker')">
                <template v-for="itemSlot in getSlot(i.key)" :key="itemSlot" v-slot:[itemSlot]="temp">
                  <slot :name="'s-'+(i.key as string[]).join('-')+'_'+itemSlot" v-bind="temp"></slot>
                </template>
              </component>
            </el-form-item>
            <!--            否则走下方逻辑-->
            <el-form-item
                v-else
                v-bind="{prop:i.key,label:i.label,...i.elFormItemAttrs}"
            >
              <slot v-if="i.type==='slot'" :name="'s-'+i.key.toString()"/>
              <component
                  v-else
                  v-bind="i.devAttrs || {}"
                  v-model="formData[i.key.toString()]"
                  :is="getComponent(i.type)">
                <template v-for="itemSlot in getSlot(i.key)" :key="itemSlot" v-slot:[itemSlot]="temp">
                  <slot :name="'s-'+i.key.toString()+'_'+itemSlot" v-bind="temp"></slot>
                </template>
              </component>
            </el-form-item>
          </el-col>
        </template>
        <el-col v-bind="props.elColAttrs">
          <el-button v-if="props.enterToSearch" native-type="submit" type="primary">{{
              props.submitBtnText
            }}
          </el-button>
          <el-button v-else native-type="button" type="primary" @click="submitForm()">{{
              props.submitBtnText
            }}
          </el-button>
          <el-button @click="resetForm()">{{ props.resetBtnText }}</el-button>
          <slot name="search-button"/>
          <a style="margin: 0 8px" v-if="props.isCollapse" class="a-box" @click="expand = !expand">
            <template v-if="expand">
              <el-icon>
                <ArrowUpBold/>
              </el-icon>
            </template>
            <template v-else>
              <el-icon>
                <ArrowDownBold/>
              </el-icon>
            </template>
            {{ expand ? '收起' : '展开' }}
          </a>
        </el-col>
      </el-row>
    </el-form>
  </el-card>
</template>

<style scoped lang="scss">
.a-box {
  font-size: 12px;
  font-weight: bolder;
  color: $frame-color-primary;
  cursor: pointer;
}
</style>
